home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / mozilla-firefox / include / js / jsemit.h < prev    next >
C/C++ Source or Header  |  2006-05-08  |  28KB  |  593 lines

  1. /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2.  *
  3.  * ***** BEGIN LICENSE BLOCK *****
  4.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  5.  *
  6.  * The contents of this file are subject to the Mozilla Public License Version
  7.  * 1.1 (the "License"); you may not use this file except in compliance with
  8.  * the License. You may obtain a copy of the License at
  9.  * http://www.mozilla.org/MPL/
  10.  *
  11.  * Software distributed under the License is distributed on an "AS IS" basis,
  12.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13.  * for the specific language governing rights and limitations under the
  14.  * License.
  15.  *
  16.  * The Original Code is Mozilla Communicator client code, released
  17.  * March 31, 1998.
  18.  *
  19.  * The Initial Developer of the Original Code is
  20.  * Netscape Communications Corporation.
  21.  * Portions created by the Initial Developer are Copyright (C) 1998
  22.  * the Initial Developer. All Rights Reserved.
  23.  *
  24.  * Contributor(s):
  25.  *
  26.  * Alternatively, the contents of this file may be used under the terms of
  27.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  28.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  29.  * in which case the provisions of the GPL or the LGPL are applicable instead
  30.  * of those above. If you wish to allow use of your version of this file only
  31.  * under the terms of either the GPL or the LGPL, and not to allow others to
  32.  * use your version of this file under the terms of the MPL, indicate your
  33.  * decision by deleting the provisions above and replace them with the notice
  34.  * and other provisions required by the GPL or the LGPL. If you do not delete
  35.  * the provisions above, a recipient may use your version of this file under
  36.  * the terms of any one of the MPL, the GPL or the LGPL.
  37.  *
  38.  * ***** END LICENSE BLOCK ***** */
  39.  
  40. #ifndef jsemit_h___
  41. #define jsemit_h___
  42. /*
  43.  * JS bytecode generation.
  44.  */
  45.  
  46. #include "jsstddef.h"
  47. #include "jstypes.h"
  48. #include "jsatom.h"
  49. #include "jsopcode.h"
  50. #include "jsprvtd.h"
  51. #include "jspubtd.h"
  52.  
  53. JS_BEGIN_EXTERN_C
  54.  
  55. /*
  56.  * NB: If you add non-loop STMT_* enumerators, do so before STMT_DO_LOOP or
  57.  * you will break the STMT_IS_LOOP macro, just below this enum.
  58.  */
  59. typedef enum JSStmtType {
  60.     STMT_BLOCK        = 0,      /* compound statement: { s1[;... sN] } */
  61.     STMT_LABEL        = 1,      /* labeled statement:  L: s */
  62.     STMT_IF           = 2,      /* if (then) statement */
  63.     STMT_ELSE         = 3,      /* else clause of if statement */
  64.     STMT_SWITCH       = 4,      /* switch statement */
  65.     STMT_WITH         = 5,      /* with statement */
  66.     STMT_TRY          = 6,      /* try statement */
  67.     STMT_CATCH        = 7,      /* catch block */
  68.     STMT_FINALLY      = 8,      /* finally statement */
  69.     STMT_SUBROUTINE   = 9,      /* gosub-target subroutine body */
  70.     STMT_DO_LOOP      = 10,     /* do/while loop statement */
  71.     STMT_FOR_LOOP     = 11,     /* for loop statement */
  72.     STMT_FOR_IN_LOOP  = 12,     /* for/in loop statement */
  73.     STMT_WHILE_LOOP   = 13      /* while loop statement */
  74. } JSStmtType;
  75.  
  76. #define STMT_IS_LOOP(stmt)      ((stmt)->type >= STMT_DO_LOOP)
  77.  
  78. typedef struct JSStmtInfo JSStmtInfo;
  79.  
  80. struct JSStmtInfo {
  81.     JSStmtType      type;           /* statement type */
  82.     ptrdiff_t       update;         /* loop update offset (top if none) */
  83.     ptrdiff_t       breaks;         /* offset of last break in loop */
  84.     ptrdiff_t       continues;      /* offset of last continue in loop */
  85.     ptrdiff_t       gosub;          /* offset of last GOSUB for this finally */
  86.     ptrdiff_t       catchJump;      /* offset of last end-of-catch jump */
  87.     JSAtom          *label;         /* name of LABEL or CATCH var */
  88.     JSStmtInfo      *down;          /* info for enclosing statement */
  89. };
  90.  
  91. #define SET_STATEMENT_TOP(stmt, top)                                          \
  92.     ((stmt)->update = (top), (stmt)->breaks =                                 \
  93.      (stmt)->continues = (stmt)->catchJump = (stmt)->gosub = (-1))
  94.  
  95. struct JSTreeContext {              /* tree context for semantic checks */
  96.     uint16          flags;          /* statement state flags, see below */
  97.     uint16          numGlobalVars;  /* max. no. of global variables/regexps */
  98.     uint32          tryCount;       /* total count of try statements parsed */
  99.     uint32          globalUses;     /* optimizable global var uses in total */
  100.     uint32          loopyGlobalUses;/* optimizable global var uses in loops */
  101.     JSStmtInfo      *topStmt;       /* top of statement info stack */
  102.     JSAtomList      decls;          /* function, const, and var declarations */
  103.     JSParseNode     *nodeList;      /* list of recyclable parse-node structs */
  104. };
  105.  
  106. #define TCF_COMPILING          0x01 /* generating bytecode; this tc is a cg */
  107. #define TCF_IN_FUNCTION        0x02 /* parsing inside function body */
  108. #define TCF_RETURN_EXPR        0x04 /* function has 'return expr;' */
  109. #define TCF_RETURN_VOID        0x08 /* function has 'return;' */
  110. #define TCF_IN_FOR_INIT        0x10 /* parsing init expr of for; exclude 'in' */
  111. #define TCF_FUN_CLOSURE_VS_VAR 0x20 /* function and var with same name */
  112. #define TCF_FUN_USES_NONLOCALS 0x40 /* function refers to non-local names */
  113. #define TCF_FUN_HEAVYWEIGHT    0x80 /* function needs Call object per call */
  114. #define TCF_FUN_FLAGS          0xE0 /* flags to propagate from FunctionBody */
  115. #define TCF_HAS_DEFXMLNS      0x100 /* default xml namespace = ...; parsed */
  116.  
  117. #define TREE_CONTEXT_INIT(tc)                                                 \
  118.     ((tc)->flags = (tc)->numGlobalVars = 0,                                   \
  119.      (tc)->tryCount = (tc)->globalUses = (tc)->loopyGlobalUses = 0,           \
  120.      (tc)->topStmt = NULL, ATOM_LIST_INIT(&(tc)->decls),                      \
  121.      (tc)->nodeList = NULL)
  122.  
  123. #define TREE_CONTEXT_FINISH(tc)                                               \
  124.     ((void)0)
  125.  
  126. /*
  127.  * Span-dependent instructions are jumps whose span (from the jump bytecode to
  128.  * the jump target) may require 2 or 4 bytes of immediate operand.
  129.  */
  130. typedef struct JSSpanDep    JSSpanDep;
  131. typedef struct JSJumpTarget JSJumpTarget;
  132.  
  133. struct JSSpanDep {
  134.     ptrdiff_t       top;        /* offset of first bytecode in an opcode */
  135.     ptrdiff_t       offset;     /* offset - 1 within opcode of jump operand */
  136.     ptrdiff_t       before;     /* original offset - 1 of jump operand */
  137.     JSJumpTarget    *target;    /* tagged target pointer or backpatch delta */
  138. };
  139.  
  140. /*
  141.  * Jump targets are stored in an AVL tree, for O(log(n)) lookup with targets
  142.  * sorted by offset from left to right, so that targets after a span-dependent
  143.  * instruction whose jump offset operand must be extended can be found quickly
  144.  * and adjusted upward (toward higher offsets).
  145.  */
  146. struct JSJumpTarget {
  147.     ptrdiff_t       offset;     /* offset of span-dependent jump target */
  148.     int             balance;    /* AVL tree balance number */
  149.     JSJumpTarget    *kids[2];   /* left and right AVL tree child pointers */
  150. };
  151.  
  152. #define JT_LEFT                 0
  153. #define JT_RIGHT                1
  154. #define JT_OTHER_DIR(dir)       (1 - (dir))
  155. #define JT_IMBALANCE(dir)       (((dir) << 1) - 1)
  156. #define JT_DIR(imbalance)       (((imbalance) + 1) >> 1)
  157.  
  158. /*
  159.  * Backpatch deltas are encoded in JSSpanDep.target if JT_TAG_BIT is clear,
  160.  * so we can maintain backpatch chains when using span dependency records to
  161.  * hold jump offsets that overflow 16 bits.
  162.  */
  163. #define JT_TAG_BIT              ((jsword) 1)
  164. #define JT_UNTAG_SHIFT          1
  165. #define JT_SET_TAG(jt)          ((JSJumpTarget *)((jsword)(jt) | JT_TAG_BIT))
  166. #define JT_CLR_TAG(jt)          ((JSJumpTarget *)((jsword)(jt) & ~JT_TAG_BIT))
  167. #define JT_HAS_TAG(jt)          ((jsword)(jt) & JT_TAG_BIT)
  168.  
  169. #define BITS_PER_PTRDIFF        (sizeof(ptrdiff_t) * JS_BITS_PER_BYTE)
  170. #define BITS_PER_BPDELTA        (BITS_PER_PTRDIFF - 1 - JT_UNTAG_SHIFT)
  171. #define BPDELTA_MAX             (((ptrdiff_t)1 << BITS_PER_BPDELTA) - 1)
  172. #define BPDELTA_TO_JT(bp)       ((JSJumpTarget *)((bp) << JT_UNTAG_SHIFT))
  173. #define JT_TO_BPDELTA(jt)       ((ptrdiff_t)((jsword)(jt) >> JT_UNTAG_SHIFT))
  174.  
  175. #define SD_SET_TARGET(sd,jt)    ((sd)->target = JT_SET_TAG(jt))
  176. #define SD_GET_TARGET(sd)       (JS_ASSERT(JT_HAS_TAG((sd)->target)),         \
  177.                                  JT_CLR_TAG((sd)->target))
  178. #define SD_SET_BPDELTA(sd,bp)   ((sd)->target = BPDELTA_TO_JT(bp))
  179. #define SD_GET_BPDELTA(sd)      (JS_ASSERT(!JT_HAS_TAG((sd)->target)),        \
  180.                                  JT_TO_BPDELTA((sd)->target))
  181.  
  182. /* Avoid asserting twice by expanding SD_GET_TARGET in the "then" clause. */
  183. #define SD_SPAN(sd,pivot)       (SD_GET_TARGET(sd)                            \
  184.                                  ? JT_CLR_TAG((sd)->target)->offset - (pivot) \
  185.                                  : 0)
  186.  
  187. struct JSCodeGenerator {
  188.     JSTreeContext   treeContext;    /* base state: statement info stack, etc. */
  189.  
  190.     JSArenaPool     *codePool;      /* pointer to thread code arena pool */
  191.     JSArenaPool     *notePool;      /* pointer to thread srcnote arena pool */
  192.     void            *codeMark;      /* low watermark in cg->codePool */
  193.     void            *noteMark;      /* low watermark in cg->notePool */
  194.     void            *tempMark;      /* low watermark in cx->tempPool */
  195.  
  196.     struct {
  197.         jsbytecode  *base;          /* base of JS bytecode vector */
  198.         jsbytecode  *limit;         /* one byte beyond end of bytecode */
  199.         jsbytecode  *next;          /* pointer to next free bytecode */
  200.         jssrcnote   *notes;         /* source notes, see below */
  201.         uintN       noteCount;      /* number of source notes so far */
  202.         uintN       noteMask;       /* growth increment for notes */
  203.         ptrdiff_t   lastNoteOffset; /* code offset for last source note */
  204.         uintN       currentLine;    /* line number for tree-based srcnote gen */
  205.     } prolog, main, *current;
  206.  
  207.     const char      *filename;      /* null or weak link to source filename */
  208.     uintN           firstLine;      /* first line, for js_NewScriptFromCG */
  209.     JSPrincipals    *principals;    /* principals for constant folding eval */
  210.     JSAtomList      atomList;       /* literals indexed for mapping */
  211.  
  212.     intN            stackDepth;     /* current stack depth in script frame */
  213.     uintN           maxStackDepth;  /* maximum stack depth so far */
  214.  
  215.     JSTryNote       *tryBase;       /* first exception handling note */
  216.     JSTryNote       *tryNext;       /* next available note */
  217.     size_t          tryNoteSpace;   /* # of bytes allocated at tryBase */
  218.  
  219.     JSSpanDep       *spanDeps;      /* span dependent instruction records */
  220.     JSJumpTarget    *jumpTargets;   /* AVL tree of jump target offsets */
  221.     JSJumpTarget    *jtFreeList;    /* JT_LEFT-linked list of free structs */
  222.     uintN           numSpanDeps;    /* number of span dependencies */
  223.     uintN           numJumpTargets; /* number of jump targets */
  224.     ptrdiff_t       spanDepTodo;    /* offset from main.base of potentially
  225.                                        unoptimized spandeps */
  226.  
  227.     uintN           emitLevel;      /* js_EmitTree recursion level */
  228.     JSAtomList      constList;      /* compile time constants */
  229.     JSCodeGenerator *parent;        /* Enclosing function or global context */
  230. };
  231.  
  232. #define CG_BASE(cg)             ((cg)->current->base)
  233. #define CG_LIMIT(cg)            ((cg)->current->limit)
  234. #define CG_NEXT(cg)             ((cg)->current->next)
  235. #define CG_CODE(cg,offset)      (CG_BASE(cg) + (offset))
  236. #define CG_OFFSET(cg)           PTRDIFF(CG_NEXT(cg), CG_BASE(cg), jsbytecode)
  237.  
  238. #define CG_NOTES(cg)            ((cg)->current->notes)
  239. #define CG_NOTE_COUNT(cg)       ((cg)->current->noteCount)
  240. #define CG_NOTE_MASK(cg)        ((cg)->current->noteMask)
  241. #define CG_LAST_NOTE_OFFSET(cg) ((cg)->current->lastNoteOffset)
  242. #define CG_CURRENT_LINE(cg)     ((cg)->current->currentLine)
  243.  
  244. #define CG_PROLOG_BASE(cg)      ((cg)->prolog.base)
  245. #define CG_PROLOG_LIMIT(cg)     ((cg)->prolog.limit)
  246. #define CG_PROLOG_NEXT(cg)      ((cg)->prolog.next)
  247. #define CG_PROLOG_CODE(cg,poff) (CG_PROLOG_BASE(cg) + (poff))
  248. #define CG_PROLOG_OFFSET(cg)    PTRDIFF(CG_PROLOG_NEXT(cg), CG_PROLOG_BASE(cg),\
  249.                                         jsbytecode)
  250.  
  251. #define CG_SWITCH_TO_MAIN(cg)   ((cg)->current = &(cg)->main)
  252. #define CG_SWITCH_TO_PROLOG(cg) ((cg)->current = &(cg)->prolog)
  253.  
  254. /*
  255.  * Initialize cg to allocate bytecode space from codePool, source note space
  256.  * from notePool, and all other arena-allocated temporaries from cx->tempPool.
  257.  * Return true on success.  Report an error and return false if the initial
  258.  * code segment can't be allocated.
  259.  */
  260. extern JS_FRIEND_API(JSBool)
  261. js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg,
  262.                      JSArenaPool *codePool, JSArenaPool *notePool,
  263.                      const char *filename, uintN lineno,
  264.                      JSPrincipals *principals);
  265.  
  266. /*
  267.  * Release cg->codePool, cg->notePool, and cx->tempPool to marks set by
  268.  * js_InitCodeGenerator.  Note that cgs are magic: they own the arena pool
  269.  * "tops-of-stack" space above their codeMark, noteMark, and tempMark points.
  270.  * This means you cannot alloc from tempPool and save the pointer beyond the
  271.  * next JS_FinishCodeGenerator.
  272.  */
  273. extern JS_FRIEND_API(void)
  274. js_FinishCodeGenerator(JSContext *cx, JSCodeGenerator *cg);
  275.  
  276. /*
  277.  * Emit one bytecode.
  278.  */
  279. extern ptrdiff_t
  280. js_Emit1(JSContext *cx, JSCodeGenerator *cg, JSOp op);
  281.  
  282. /*
  283.  * Emit two bytecodes, an opcode (op) with a byte of immediate operand (op1).
  284.  */
  285. extern ptrdiff_t
  286. js_Emit2(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1);
  287.  
  288. /*
  289.  * Emit three bytecodes, an opcode with two bytes of immediate operands.
  290.  */
  291. extern ptrdiff_t
  292. js_Emit3(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1,
  293.          jsbytecode op2);
  294.  
  295. /*
  296.  * Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
  297.  */
  298. extern ptrdiff_t
  299. js_EmitN(JSContext *cx, JSCodeGenerator *cg, JSOp op, size_t extra);
  300.  
  301. /*
  302.  * Unsafe macro to call js_SetJumpOffset and return false if it does.
  303.  */
  304. #define CHECK_AND_SET_JUMP_OFFSET(cx,cg,pc,off)                               \
  305.     JS_BEGIN_MACRO                                                            \
  306.         if (!js_SetJumpOffset(cx, cg, pc, off))                               \
  307.             return JS_FALSE;                                                  \
  308.     JS_END_MACRO
  309.  
  310. #define CHECK_AND_SET_JUMP_OFFSET_AT(cx,cg,off)                               \
  311.     CHECK_AND_SET_JUMP_OFFSET(cx, cg, CG_CODE(cg,off), CG_OFFSET(cg) - (off))
  312.  
  313. extern JSBool
  314. js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc,
  315.                  ptrdiff_t off);
  316.  
  317. /* Test whether we're in a with statement. */
  318. extern JSBool
  319. js_InWithStatement(JSTreeContext *tc);
  320.  
  321. /* Test whether we're in a catch block with exception named by atom. */
  322. extern JSBool
  323. js_InCatchBlock(JSTreeContext *tc, JSAtom *atom);
  324.  
  325. /*
  326.  * Push the C-stack-allocated struct at stmt onto the stmtInfo stack.
  327.  */
  328. extern void
  329. js_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type,
  330.                  ptrdiff_t top);
  331.  
  332. /*
  333.  * Pop tc->topStmt.  If the top JSStmtInfo struct is not stack-allocated, it
  334.  * is up to the caller to free it.
  335.  */
  336. extern void
  337. js_PopStatement(JSTreeContext *tc);
  338.  
  339. /*
  340.  * Like js_PopStatement(&cg->treeContext), also patch breaks and continues.
  341.  * May fail if a jump offset overflows.
  342.  */
  343. extern JSBool
  344. js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg);
  345.  
  346. /*
  347.  * Define and lookup a primitive jsval associated with the const named by atom.
  348.  * js_DefineCompileTimeConstant analyzes the constant-folded initializer at pn
  349.  * and saves the const's value in cg->constList, if it can be used at compile
  350.  * time.  It returns true unless an error occurred.
  351.  *
  352.  * If the initializer's value could not be saved, js_LookupCompileTimeConstant
  353.  * calls will return the undefined value.  js_LookupCompileTimeConstant tries
  354.  * to find a const value memorized for atom, returning true with *vp set to a
  355.  * value other than undefined if the constant was found, true with *vp set to
  356.  * JSVAL_VOID if not found, and false on error.
  357.  */
  358. extern JSBool
  359. js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
  360.                              JSParseNode *pn);
  361.  
  362. extern JSBool
  363. js_LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
  364.                              jsval *vp);
  365.  
  366. /*
  367.  * Emit code into cg for the tree rooted at pn.
  368.  */
  369. extern JSBool
  370. js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn);
  371.  
  372. /*
  373.  * Emit code into cg for the tree rooted at body, then create a persistent
  374.  * script for fun from cg.
  375.  */
  376. extern JSBool
  377. js_EmitFunctionBody(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body,
  378.                     JSFunction *fun);
  379.  
  380. /*
  381.  * Source notes generated along with bytecode for decompiling and debugging.
  382.  * A source note is a uint8 with 5 bits of type and 3 of offset from the pc of
  383.  * the previous note.  If 3 bits of offset aren't enough, extended delta notes
  384.  * (SRC_XDELTA) consisting of 2 set high order bits followed by 6 offset bits
  385.  * are emitted before the next note.  Some notes have operand offsets encoded
  386.  * immediately after them, in note bytes or byte-triples.
  387.  *
  388.  *                 Source Note               Extended Delta
  389.  *              +7-6-5-4-3+2-1-0+           +7-6-5+4-3-2-1-0+
  390.  *              |note-type|delta|           |1 1| ext-delta |
  391.  *              +---------+-----+           +---+-----------+
  392.  *
  393.  * At most one "gettable" note (i.e., a note of type other than SRC_NEWLINE,
  394.  * SRC_SETLINE, and SRC_XDELTA) applies to a given bytecode.
  395.  *
  396.  * NB: the js_SrcNoteSpec array in jsemit.c is indexed by this enum, so its
  397.  * initializers need to match the order here.
  398.  */
  399. typedef enum JSSrcNoteType {
  400.     SRC_NULL        = 0,        /* terminates a note vector */
  401.     SRC_IF          = 1,        /* JSOP_IFEQ bytecode is from an if-then */
  402.     SRC_IF_ELSE     = 2,        /* JSOP_IFEQ bytecode is from an if-then-else */
  403.     SRC_WHILE       = 3,        /* JSOP_IFEQ is from a while loop */
  404.     SRC_FOR         = 4,        /* JSOP_NOP or JSOP_POP in for loop head */
  405.     SRC_CONTINUE    = 5,        /* JSOP_GOTO is a continue, not a break;
  406.                                    also used on JSOP_ENDINIT if extra comma
  407.                                    at end of array literal: [1,2,,] */
  408.     SRC_VAR         = 6,        /* JSOP_NAME/SETNAME/FORNAME in a var decl */
  409.     SRC_PCDELTA     = 7,        /* distance from comma-operator to next POP,
  410.                                    or from CONDSWITCH to first CASE opcode --
  411.                                    or SRC_PCBASE variant for obj.function::foo
  412.                                    gets and sets */
  413.     SRC_ASSIGNOP    = 8,        /* += or another assign-op follows */
  414.     SRC_COND        = 9,        /* JSOP_IFEQ is from conditional ?: operator */
  415.     SRC_RESERVED0   = 10,       /* reserved for future use */
  416.     SRC_HIDDEN      = 11,       /* opcode shouldn't be decompiled */
  417.     SRC_PCBASE      = 12,       /* distance back from annotated get- or setprop
  418.                                    op to first obj.prop.subprop bytecode */
  419.     SRC_LABEL       = 13,       /* JSOP_NOP for label: with atomid immediate */
  420.     SRC_LABELBRACE  = 14,       /* JSOP_NOP for label: {...} begin brace */
  421.     SRC_ENDBRACE    = 15,       /* JSOP_NOP for label: {...} end brace */
  422.     SRC_BREAK2LABEL = 16,       /* JSOP_GOTO for 'break label' with atomid */
  423.     SRC_CONT2LABEL  = 17,       /* JSOP_GOTO for 'continue label' with atomid */
  424.     SRC_SWITCH      = 18,       /* JSOP_*SWITCH with offset to end of switch,
  425.                                    2nd off to first JSOP_CASE if condswitch */
  426.     SRC_FUNCDEF     = 19,       /* JSOP_NOP for function f() with atomid */
  427.     SRC_CATCH       = 20,       /* catch block has guard */
  428.     SRC_CONST       = 21,       /* JSOP_SETCONST in a const decl */
  429.     SRC_NEWLINE     = 22,       /* bytecode follows a source newline */
  430.     SRC_SETLINE     = 23,       /* a file-absolute source line number note */
  431.     SRC_XDELTA      = 24        /* 24-31 are for extended delta notes */
  432. } JSSrcNoteType;
  433.  
  434. #define SN_TYPE_BITS            5
  435. #define SN_DELTA_BITS           3
  436. #define SN_XDELTA_BITS          6
  437. #define SN_TYPE_MASK            (JS_BITMASK(SN_TYPE_BITS) << SN_DELTA_BITS)
  438. #define SN_DELTA_MASK           ((ptrdiff_t)JS_BITMASK(SN_DELTA_BITS))
  439. #define SN_XDELTA_MASK          ((ptrdiff_t)JS_BITMASK(SN_XDELTA_BITS))
  440.  
  441. #define SN_MAKE_NOTE(sn,t,d)    (*(sn) = (jssrcnote)                          \
  442.                                           (((t) << SN_DELTA_BITS)             \
  443.                                            | ((d) & SN_DELTA_MASK)))
  444. #define SN_MAKE_XDELTA(sn,d)    (*(sn) = (jssrcnote)                          \
  445.                                           ((SRC_XDELTA << SN_DELTA_BITS)      \
  446.                                            | ((d) & SN_XDELTA_MASK)))
  447.  
  448. #define SN_IS_XDELTA(sn)        ((*(sn) >> SN_DELTA_BITS) >= SRC_XDELTA)
  449. #define SN_TYPE(sn)             (SN_IS_XDELTA(sn) ? SRC_XDELTA                \
  450.                                                   : *(sn) >> SN_DELTA_BITS)
  451. #define SN_SET_TYPE(sn,type)    SN_MAKE_NOTE(sn, type, SN_DELTA(sn))
  452. #define SN_IS_GETTABLE(sn)      (SN_TYPE(sn) < SRC_NEWLINE)
  453.  
  454. #define SN_DELTA(sn)            ((ptrdiff_t)(SN_IS_XDELTA(sn)                 \
  455.                                              ? *(sn) & SN_XDELTA_MASK         \
  456.                                              : *(sn) & SN_DELTA_MASK))
  457. #define SN_SET_DELTA(sn,delta)  (SN_IS_XDELTA(sn)                             \
  458.                                  ? SN_MAKE_XDELTA(sn, delta)                  \
  459.                                  : SN_MAKE_NOTE(sn, SN_TYPE(sn), delta))
  460.  
  461. #define SN_DELTA_LIMIT          ((ptrdiff_t)JS_BIT(SN_DELTA_BITS))
  462. #define SN_XDELTA_LIMIT         ((ptrdiff_t)JS_BIT(SN_XDELTA_BITS))
  463.  
  464. /*
  465.  * Offset fields follow certain notes and are frequency-encoded: an offset in
  466.  * [0,0x7f] consumes one byte, an offset in [0x80,0x7fffff] takes three, and
  467.  * the high bit of the first byte is set.
  468.  */
  469. #define SN_3BYTE_OFFSET_FLAG    0x80
  470. #define SN_3BYTE_OFFSET_MASK    0x7f
  471.  
  472. typedef struct JSSrcNoteSpec {
  473.     const char      *name;      /* name for disassembly/debugging output */
  474.     uint8           arity;      /* number of offset operands */
  475.     uint8           offsetBias; /* bias of offset(s) from annotated pc */
  476.     int8            isSpanDep;  /* 1 or -1 if offsets could span extended ops,
  477.                                    0 otherwise; sign tells span direction */
  478. } JSSrcNoteSpec;
  479.  
  480. extern JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[];
  481. extern JS_FRIEND_API(uintN)          js_SrcNoteLength(jssrcnote *sn);
  482.  
  483. #define SN_LENGTH(sn)           ((js_SrcNoteSpec[SN_TYPE(sn)].arity == 0) ? 1 \
  484.                                  : js_SrcNoteLength(sn))
  485. #define SN_NEXT(sn)             ((sn) + SN_LENGTH(sn))
  486.  
  487. /* A source note array is terminated by an all-zero element. */
  488. #define SN_MAKE_TERMINATOR(sn)  (*(sn) = SRC_NULL)
  489. #define SN_IS_TERMINATOR(sn)    (*(sn) == SRC_NULL)
  490.  
  491. /*
  492.  * Append a new source note of the given type (and therefore size) to cg's
  493.  * notes dynamic array, updating cg->noteCount.  Return the new note's index
  494.  * within the array pointed at by cg->current->notes.  Return -1 if out of
  495.  * memory.
  496.  */
  497. extern intN
  498. js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type);
  499.  
  500. extern intN
  501. js_NewSrcNote2(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
  502.                ptrdiff_t offset);
  503.  
  504. extern intN
  505. js_NewSrcNote3(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
  506.                ptrdiff_t offset1, ptrdiff_t offset2);
  507.  
  508. /*
  509.  * NB: this function can add at most one extra extended delta note.
  510.  */
  511. extern jssrcnote *
  512. js_AddToSrcNoteDelta(JSContext *cx, JSCodeGenerator *cg, jssrcnote *sn,
  513.                      ptrdiff_t delta);
  514.  
  515. /*
  516.  * Get and set the offset operand identified by which (0 for the first, etc.).
  517.  */
  518. extern JS_FRIEND_API(ptrdiff_t)
  519. js_GetSrcNoteOffset(jssrcnote *sn, uintN which);
  520.  
  521. extern JSBool
  522. js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index,
  523.                     uintN which, ptrdiff_t offset);
  524.  
  525. /*
  526.  * Finish taking source notes in cx's notePool, copying final notes to the new
  527.  * stable store allocated by the caller and passed in via notes.  Return false
  528.  * on malloc failure, which means this function reported an error.
  529.  *
  530.  * To compute the number of jssrcnotes to allocate and pass in via notes, use
  531.  * the CG_COUNT_FINAL_SRCNOTES macro.  This macro knows a lot about details of
  532.  * js_FinishTakingSrcNotes, SO DON'T CHANGE jsemit.c's js_FinishTakingSrcNotes
  533.  * FUNCTION WITHOUT CHECKING WHETHER THIS MACRO NEEDS CORRESPONDING CHANGES!
  534.  */
  535. #define CG_COUNT_FINAL_SRCNOTES(cg, cnt)                                      \
  536.     JS_BEGIN_MACRO                                                            \
  537.         ptrdiff_t diff_ = CG_PROLOG_OFFSET(cg) - (cg)->prolog.lastNoteOffset; \
  538.         cnt = (cg)->prolog.noteCount + (cg)->main.noteCount + 1;              \
  539.         if ((cg)->prolog.noteCount &&                                         \
  540.             (cg)->prolog.currentLine != (cg)->firstLine) {                    \
  541.             if (diff_ > SN_DELTA_MASK)                                        \
  542.                 cnt += JS_HOWMANY(diff_ - SN_DELTA_MASK, SN_XDELTA_MASK);     \
  543.             cnt += 2 + (((cg)->firstLine > SN_3BYTE_OFFSET_MASK) << 1);       \
  544.         } else if (diff_ > 0) {                                               \
  545.             if (cg->main.noteCount) {                                         \
  546.                 jssrcnote *sn_ = (cg)->main.notes;                            \
  547.                 diff_ -= SN_IS_XDELTA(sn_)                                    \
  548.                          ? SN_XDELTA_MASK - (*sn_ & SN_XDELTA_MASK)           \
  549.                          : SN_DELTA_MASK - (*sn_ & SN_DELTA_MASK);            \
  550.             }                                                                 \
  551.             if (diff_ > 0)                                                    \
  552.                 cnt += JS_HOWMANY(diff_, SN_XDELTA_MASK);                     \
  553.         }                                                                     \
  554.     JS_END_MACRO
  555.  
  556. extern JSBool
  557. js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg, jssrcnote *notes);
  558.  
  559. /*
  560.  * Allocate cg->treeContext.tryCount notes (plus one for the end sentinel)
  561.  * from cx->tempPool and set up cg->tryBase/tryNext for exactly tryCount
  562.  * js_NewTryNote calls.  The storage is freed by js_FinishCodeGenerator.
  563.  */
  564. extern JSBool
  565. js_AllocTryNotes(JSContext *cx, JSCodeGenerator *cg);
  566.  
  567. /*
  568.  * Grab the next trynote slot in cg, filling it in appropriately.
  569.  */
  570. extern JSTryNote *
  571. js_NewTryNote(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t start,
  572.               ptrdiff_t end, ptrdiff_t catchStart);
  573.  
  574. /*
  575.  * Finish generating exception information into the space at notes.  As with
  576.  * js_FinishTakingSrcNotes, the caller must use CG_COUNT_FINAL_TRYNOTES(cg) to
  577.  * preallocate enough space in a JSTryNote[] to pass as the notes parameter of
  578.  * js_FinishTakingTryNotes.
  579.  */
  580. #define CG_COUNT_FINAL_TRYNOTES(cg, cnt)                                      \
  581.     JS_BEGIN_MACRO                                                            \
  582.         cnt = ((cg)->tryNext > (cg)->tryBase)                                 \
  583.               ? PTRDIFF(cg->tryNext, cg->tryBase, JSTryNote) + 1              \
  584.               : 0;                                                            \
  585.     JS_END_MACRO
  586.  
  587. extern void
  588. js_FinishTakingTryNotes(JSContext *cx, JSCodeGenerator *cg, JSTryNote *notes);
  589.  
  590. JS_END_EXTERN_C
  591.  
  592. #endif /* jsemit_h___ */
  593.